package untils

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"log"
	"shop/common/global"
	"shop/common/inits"
	"shop/common/model"
	"strconv"
)

// SearchGoodsInES 从Elasticsearch中搜索商品
// 功能: 根据关键词搜索商品，支持分页
// 参数:
//   - keyword: 搜索关键词
//   - page: 页码
//   - pageSize: 每页数量
//
// 返回值:
//   - []model.Goods: 商品列表
//   - int: 总条数
//   - error: 错误信息
func SearchGoodsInES(keyword string, page, pageSize int) ([]model.Goods, int, error) {
	var goodsList []model.Goods
	var total int

	// 构建查询DSL
	var buf bytes.Buffer

	// 如果没有关键词，查询所有商品；否则进行模糊搜索
	if keyword == "" {
		// 查询所有商品
		query := map[string]interface{}{
			"query": map[string]interface{}{
				"match_all": map[string]interface{}{},
			},
			"from": (page - 1) * pageSize,
			"size": pageSize,
		}
		if err := json.NewEncoder(&buf).Encode(query); err != nil {
			return nil, 0, fmt.Errorf("error encoding query: %w", err)
		}
	} else {
		// 关键词搜索
		query := map[string]interface{}{
			"query": map[string]interface{}{
				"match": map[string]interface{}{
					"title": map[string]interface{}{
						"query":    keyword,
						"analyzer": "ik_smart",
					},
				},
			},
			"from": (page - 1) * pageSize,
			"size": pageSize,
		}
		if err := json.NewEncoder(&buf).Encode(query); err != nil {
			return nil, 0, fmt.Errorf("error encoding query: %w", err)
		}
	}

	// 执行搜索请求
	res, err := inits.ESClient.Search(
		inits.ESClient.Search.WithContext(context.Background()),
		inits.ESClient.Search.WithIndex("goods"),
		inits.ESClient.Search.WithBody(&buf),
		inits.ESClient.Search.WithTrackTotalHits(true),
		inits.ESClient.Search.WithPretty(),
	)
	if err != nil {
		return nil, 0, fmt.Errorf("error getting response: %w", err)
	}
	defer res.Body.Close()

	if res.IsError() {
		return nil, 0, fmt.Errorf("search request failed: %s", res.Status())
	}

	// 解析响应
	var result map[string]interface{}
	if err := json.NewDecoder(res.Body).Decode(&result); err != nil {
		return nil, 0, fmt.Errorf("error parsing the response body: %w", err)
	}

	// 提取总条数
	hits, ok := result["hits"].(map[string]interface{})
	if !ok {
		return nil, 0, fmt.Errorf("invalid response structure")
	}

	totalValue, ok := hits["total"].(map[string]interface{})
	if ok {
		total = int(totalValue["value"].(float64))
	}

	// 提取商品列表
	hitsArray, ok := hits["hits"].([]interface{})
	if !ok {
		return nil, 0, fmt.Errorf("invalid hits structure")
	}

	for _, hit := range hitsArray {
		hitMap, ok := hit.(map[string]interface{})
		if !ok {
			continue
		}

		source, ok := hitMap["_source"].(map[string]interface{})
		if !ok {
			continue
		}

		// 解析商品数据
		goods := model.Goods{}
		if id, ok := source["id"].(float64); ok {
			goods.Id = uint32(id)
		}
		if title, ok := source["title"].(string); ok {
			goods.Title = title
		}
		if image, ok := source["image"].(string); ok {
			goods.Image = image
		}
		if price, ok := source["good_price"].(float64); ok {
			goods.GoodPrice = price
		}
		if stock, ok := source["good_stock"].(float64); ok {
			goods.GoodStock = int32(stock)
		}
		if status, ok := source["good_status"].(float64); ok {
			goods.GoodStatus = int32(status)
		}

		goodsList = append(goodsList, goods)
	}

	return goodsList, total, nil
}

// SyncGoodsToES 将MySQL中的商品数据同步到Elasticsearch
// 功能: 从MySQL查询商品数据并同步到ES
// 返回值:
//   - error: 错误信息
func SyncGoodsToES() error {
	// 创建索引（如果不存在）
	if err := inits.CreateGoodsIndex("goods"); err != nil {
		return fmt.Errorf("failed to create goods index: %w", err)
	}

	// 从MySQL查询商品数据
	var goodsList []model.Goods
	result := global.DB.Find(&goodsList)
	if result.Error != nil {
		return fmt.Errorf("failed to query goods from mysql: %w", result.Error)
	}

	log.Printf("Found %d goods to sync", len(goodsList))

	// 批量同步到ES
	for _, goods := range goodsList {
		if err := indexGoodsToES(goods); err != nil {
			log.Printf("Failed to sync goods %d: %v", goods.Id, err)
		}
	}

	log.Println("Goods data sync to Elasticsearch completed")
	return nil
}

// indexGoodsToES 将单个商品索引到Elasticsearch
// 功能: 将单个商品数据索引到ES
// 参数:
//   - goods: 商品数据
//
// 返回值:
//   - error: 错误信息
func indexGoodsToES(goods model.Goods) error {
	// 构建文档数据
	doc := map[string]interface{}{
		"id":          goods.Id,
		"title":       goods.Title,
		"image":       goods.Image,
		"good_price":  goods.GoodPrice,
		"good_stock":  goods.GoodStock,
		"good_status": goods.GoodStatus,
		"create_time": goods.CreateTime,
		"update_time": goods.UpdateTime,
	}

	// 序列化文档数据
	var buf bytes.Buffer
	if err := json.NewEncoder(&buf).Encode(doc); err != nil {
		return fmt.Errorf("error encoding document: %w", err)
	}

	// 执行索引请求
	res, err := inits.ESClient.Index(
		"goods",
		&buf,
		inits.ESClient.Index.WithContext(context.Background()),
		inits.ESClient.Index.WithDocumentID(strconv.Itoa(int(goods.Id))),
		inits.ESClient.Index.WithRefresh("true"),
	)
	if err != nil {
		return fmt.Errorf("error getting response: %w", err)
	}
	defer res.Body.Close()

	if res.IsError() {
		return fmt.Errorf("indexing document failed: %s", res.Status())
	}

	return nil
}

// UpdateGoodsInES 更新ES中的商品数据
// 功能: 更新ES中指定商品的数据
// 参数:
//   - goods: 更新后的商品数据
//
// 返回值:
//   - error: 错误信息
//func UpdateGoodsInES(goods model.Goods) error {
//	return indexGoodsToES(goods) // 由于ES是文档型数据库，更新可以直接使用索引操作覆盖
//}

// DeleteGoodsFromES 从ES中删除商品数据
// 功能: 从ES中删除指定ID的商品
// 参数:
//   - goodsId: 商品ID
//
// 返回值:
//   - error: 错误信息
func DeleteGoodsFromES(goodsId uint32) error {
	res, err := inits.ESClient.Delete(
		"goods",
		strconv.Itoa(int(goodsId)),
		inits.ESClient.Delete.WithContext(context.Background()),
		inits.ESClient.Delete.WithRefresh("true"),
	)
	if err != nil {
		return fmt.Errorf("error getting response: %w", err)
	}
	defer res.Body.Close()

	if res.IsError() {
		return fmt.Errorf("deleting document failed: %s", res.Status())
	}

	return nil
}
